feat(cli): add Cursor agent support and agent-aware devcontainer/proxy bootstrap#53
feat(cli): add Cursor agent support and agent-aware devcontainer/proxy bootstrap#53wiacekm wants to merge 9 commits intoVirtusLab:masterfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR generalizes the sandcat CLI + devcontainer bootstrap to support multiple agents (Claude and Cursor) by introducing agent-aware template customization, agent-specific mitmproxy addons, and new user settings templates, with corresponding updates across tests and docs.
Changes:
- Add agent plumbing (
agents.bash) and wire it through init/devcontainer/template customization paths. - Introduce Cursor support via new settings template + dedicated mitmproxy addon, plus updated devcontainer/proxy templates with agent placeholders.
- Update bootstrap scripts, docs, and bats/pytest coverage to validate Cursor/Claude behavior.
Reviewed changes
Copilot reviewed 24 out of 26 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| cli/test/mitmproxy/test_mitmproxy_addon.py | Extends mitmproxy addon tests to cover Cursor streaming and placeholder behavior. |
| cli/test/init/user_settings.bats | Adds Cursor user-settings assertions and cursor-default backfill test. |
| cli/test/init/stacks.bats | Adds zig extension mapping coverage. |
| cli/test/init/regression.bats | Adds regression coverage for Cursor devcontainer compose output and mounts. |
| cli/test/init/init.bats | Verifies init accepts cursor agent and updated interactive agent selection. |
| cli/test/init/extensions.bats | Adds tests for agent template customization (Cursor/Claude placeholders). |
| cli/test/composefile/composefile.bats | Adds Cursor config volume tests and Cursor default-mount behavior. |
| cli/templates/settings-user-cursor.json | New Cursor-focused default user settings template (secrets + network allowlist). |
| cli/templates/settings-user-claude.json | New explicit Claude user settings template (renamed from generic). |
| cli/templates/devcontainer/sandcat/scripts/mitmproxy_addon_cursor.py | New Cursor-focused mitmproxy addon with streaming-safe behavior. |
| cli/templates/devcontainer/sandcat/scripts/mitmproxy_addon_claude.py | Minor formatting tweaks to Claude addon. |
| cli/templates/devcontainer/sandcat/scripts/app-user-init.sh | Makes agent bootstrap injectable via __AGENT_USER_INIT__ and fixes HOME handling. |
| cli/templates/devcontainer/sandcat/scripts/app-init.sh | Hardens trust/proxy env handling (adds NODE_OPTIONS and CA env exports) and preserves env into user-init. |
| cli/templates/devcontainer/sandcat/compose-proxy.yml | Parameterizes mitmproxy command/addon via agent placeholders and adds mitmproxy tuning flags. |
| cli/templates/devcontainer/devcontainer.json | Replaces Claude-specific VS Code extension/settings with agent placeholders. |
| cli/templates/devcontainer/compose-all.yml | Replaces hardcoded agent env with an agent environment placeholder block. |
| cli/templates/devcontainer/Dockerfile.app | Replaces Claude install/home prep with agent placeholders. |
| cli/libexec/init/init | Makes init agent-aware for settings template selection and Cursor defaults/help text. |
| cli/libexec/init/devcontainer | Ensures agent template customization runs during devcontainer generation. |
| cli/lib/stacks.bash | Fixes zig extension mapping (but stack validation list needs updating). |
| cli/lib/logging.bash | Makes color logging best-effort even when tput/TERM is unavailable. |
| cli/lib/devcontainer.bash | Adds customize_agent_templates to render agent placeholders across templates. |
| cli/lib/composefile.bash | Adds Cursor config mounts and agent-aware volume logic in compose customization. |
| cli/lib/agents.bash | New agent abstraction: supported agents, extensions, settings/env/docker/user-init blocks. |
| cli/README.md | Documents Cursor agent support and updates CLI option descriptions. |
| README.md | Adds Cursor CLI documentation and updates trust-store guidance (NODE_OPTIONS + CA env vars). |
Comments suppressed due to low confidence (2)
cli/libexec/init/devcontainer:108
- When
--proxy tuiis selected,set_proxy_tui_moderewrites the mitmproxy command. With this PR, the proxy template uses agent-specific addon filenames (e.g.mitmproxy_addon_claude.py/mitmproxy_addon_cursor.py), butset_proxy_tui_modestill hardcodes/scripts/mitmproxy_addon.py, which will fail (and also discards the new--set http2=...etc. options). Updateset_proxy_tui_modeto preserve/use the agent-specific addon already in the template (or accept the addon filename as a parameter).
customize_agent_templates "$devcontainer_dir" "$agent"
if [[ "$proxy_mode" == "tui" ]]; then
set_proxy_tui_mode "$devcontainer_dir/sandcat/compose-proxy.yml"
fi
cli/README.md:20
- The
--stackshelp text lists supported stacks but doesn't mentionzig, while the code/tests now include azigstack extension mapping. Once stack validation is updated to actually allowzig, consider adding it to this list (or otherwise remove the zig mapping/tests) to keep CLI docs consistent with supported stacks.
- `--agent` - Agent type: `claude`, `cursor` (skips prompt)
- `--ide` - IDE for devcontainer mode: `vscode`, `jetbrains`, `none` (skips prompt)
- `--stacks` - Comma-separated development stacks to install: `node`, `python`, `java`, `rust`, `go`, `scala`, `ruby`, `dotnet` (skips prompt)
- `--proxy` - Proxy UI mode: `web` (default, mitmweb browser UI) or `tui` (mitmproxy console, use with `sandcat proxy` to attach)
- `--features` - Comma-separated optional features: `tui` (proxy console mode), `1password` (1Password secret resolution via `op` CLI)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| Cursor CLI support is available via `sandcat init --agent cursor`. | ||
|
|
||
| - The current template uses temporary compatibility defaults for auth/network. |
There was a problem hiding this comment.
maybe it would be good to write what these are exactly - to be upfront with the users for anything security-related. I'd be curious, as well ;)
There was a problem hiding this comment.
I think it should be more meaningful now
| Cursor-focused mitmproxy addon: network policy + secret substitution. | ||
|
|
||
| This variant keeps Cursor Connect streaming traffic opaque (no body mutation) | ||
| while still applying placeholder substitution in URL/headers/basic auth. |
There was a problem hiding this comment.
maybe we can somehow add the conditiona cursor logic to the original script? having two copies seems like a maintenance problem going forward
There was a problem hiding this comment.
Initially I thought about doing it in separate, but maybe it would be better to do it as a part of this PR.
|
Claude's review using my review agents: |
… fixes - Add agent-specific mitmproxy addons (cursor streaming-safe substitution, claude variant) and trim shared mitmproxy_addon.py responsibilities - Wire Cursor bootstrap (sandcat-secrets.json, auth.json, CURSOR_API_KEY override, CURSOR_USE_HTTP1_FOR_AGENT → cli-config) via agents.bash and devcontainer templates - Harden mitmproxy service command: http2 profile placeholder, set stream_large_bodies=1m (avoid 1-byte threshold streaming tiny POST bodies) - Extend init/composefile/devcontainer tests, mitmproxy addon pytest
Remove Cursor startup logic that read sandcat-secrets.json and wrote auth/env overrides. Keep placeholder-based CURSOR_API_KEY flow with proxy-side substitution and update related init test expectations.
Install GitHub CLI from the official apt repository, auto-register mounted workspaces as safe git directories, and align Cursor/stack docs and tests with current behavior. Also preserve agent-specific mitmproxy addon flags when switching proxy mode to TUI. Made-with: Cursor
d37dfda to
91026b4
Compare
- Updated README to clarify temporary compatibility defaults for Cursor, including auth passthrough, HTTP/1 compatibility, and tuned proxy command defaults. - Adjusted `set_proxy_tui_mode` to ensure correct command substitution for mitmproxy. - Modified devcontainer script to enable HTTP/2 for Cursor. - Improved user settings template path handling in init script to provide clearer error messaging. - Refined app-init and app-user-init scripts for better environment variable handling. - Removed unused secrets handling in Cursor addon to streamline configuration. These changes aim to improve the stability and usability of the Cursor integration within the Sandcat environment.
91026b4 to
b9f4488
Compare
- Add mitmproxy_addon_common.py with base SandcatAddon and hook overrides - Reduce mitmproxy_addon_claude.py and mitmproxy_addon_cursor.py to thin variants - Mount common module in compose-proxy for mitmproxy container - Rewrite tests: parametrize shared behavior; add cursor-specific and lib tests - Document two addon variants and shared module in README Made-with: Cursor
Per-agent mitmproxy streaming flags (Cursor only); path-only Cursor streaming detection and docstring updates. Pre-create host ~/.claude and ~/.cursor paths when optional mounts are enabled; compose agent environment via yq when non-empty. Extract apply_template_placeholders / apply_inline_placeholders; replace init hard-codes with sct_agent_post_user_settings_hook and sct_agent_op_api_key_help. Add cli/test/agents/agents.bats; extend mitm addon tests; dedupe extensions and composefile bats; document mitm/Cursor policy in README. Made-with: Cursor
765a32a to
ab95b0b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 29 out of 30 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Strip --web-host and --set web_password when switching mitmproxy to mitmdump so TUI mode starts reliably, and update composefile tests to assert the corrected command output. Made-with: Cursor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 29 out of 30 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| """Default: pass-through. Subclasses may strip whitespace / BOM.""" | ||
| return "" if value is None else value |
There was a problem hiding this comment.
_normalize_secret_value is annotated to return str, but the default implementation returns the original value unchanged when it is not None. If a user accidentally sets a non-string secret value in settings (e.g., number/bool), later substitution paths call .replace(...) and .encode("utf-8") on it and will crash. Consider coercing to str in the base implementation (and keep the Cursor override for additional trimming) so all secrets are safe for string/bytes substitution.
| """Default: pass-through. Subclasses may strip whitespace / BOM.""" | |
| return "" if value is None else value | |
| """Default: coerce to string. Subclasses may strip whitespace / BOM.""" | |
| return "" if value is None else str(value) |
Summary
This PR generalizes the sandcat CLI/devcontainer bootstrap to support multiple agents (Claude and Cursor) instead of a Claude-only path, and updates proxy + settings templates accordingly.
Key changes
settings-user-cursor.json).settings-user-claude.jsonfor explicit agent targeting.Why
Agent-specific assumptions in bootstrap and template generation made Cursor support brittle and increased maintenance cost. This change establishes a single agent-aware flow, reduces hardcoded behavior, and keeps proxy/trust configuration consistent across supported agents.
Test plan
batstests undercli/testand confirm updated suites pass.